package com.sdy.hospitalguard.web.controller;

import com.alibaba.excel.EasyExcel;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.sdy.common.model.BizException;
import com.sdy.common.model.Response;
import com.sdy.common.utils.Assert;
import com.sdy.common.utils.DateUtil;
import com.sdy.hospitalguard.biz.constants.RedisConstants;
import com.sdy.hospitalguard.biz.dto.*;
import com.sdy.hospitalguard.biz.model.*;
import com.sdy.hospitalguard.biz.service.*;
import com.sdy.hospitalguard.web.vo.TodayHospital;
import com.sdy.hospitalguard.web.vo.TodayHospitalVO;
import com.sdy.mvc.controller.BaseController;
import io.swagger.annotations.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.integration.redis.util.RedisLockRegistry;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URISyntaxException;
import java.net.URLDecoder;
import java.nio.charset.StandardCharsets;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Lock;
import java.util.stream.Collectors;

/**
 * @author: 王越洋
 * @version: v1.0
 * @description: com.sdy.hospitalguard.web.controller
 * @date:2020/5/15
 */

@Slf4j
@RestController
@RequestMapping("/todaySituation")
@Api(tags = "今日医院接口")
public class TodayHospitalController extends BaseController {
    @Autowired
    private HospitalUserService hospitalUserService;
    @Autowired
    private PatientInformationService patientInformationService;
    @Autowired
    private VisitAppointmentService visitAppointmentService;
    @Autowired
    private EscortAssociatedService escortAssociatedService;
    @Autowired
    private NoticeService noticeService;
    @Autowired
    private RedisLockRegistry redisLockRegistry;
    @Autowired
    private RoleService roleService;
    @Autowired
    private ManagerService managerService;

    @GetMapping("/hospital")
    @ApiOperation(value = "今日医院情况", response = TodayHospital.class)
    public Response todayPatient() {
        Calendar cal = Calendar.getInstance();
        cal.add(Calendar.DATE, -1);
        String yesterday = new SimpleDateFormat("yyyy-MM-dd").format(cal.getTime());
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat(DateUtil.DATE_FORMAT);
        String today = simpleDateFormat.format(new Date());
        //住院患者累计
        Integer count = patientInformationService.lambdaQuery().eq(PatientInformation::getPatientState, 0).count();
        //今日住院
        Integer todayPatient = patientInformationService.lambdaQuery()
                .like(PatientInformation::getAdmissionTime, today)
                .eq(PatientInformation::getPatientState, 0)
                .count();
        //昨日住院
        Integer yesterdayPatient = patientInformationService.lambdaQuery()
                .like(PatientInformation::getAdmissionTime, yesterday)
                .eq(PatientInformation::getPatientState, 0)
                .count();
        //陪护总数
        List<EscortAssociated> list = escortAssociatedService.lambdaQuery()
                .eq(EscortAssociated::getAttendantState, 0)
                .in(EscortAssociated::getFlowState, 0, 1)
                .list();
        List<Integer> ids = new ArrayList<>();
        List<EscortAssociated> collect = new ArrayList<>();
        if (list.size() > 0) {
            collect = list.stream().filter(v -> {
                boolean flag = !ids.contains(v.getUserId());
                ids.add(v.getUserId());
                return flag;
            }).collect(Collectors.toList());
        }

        List<EscortAssociated> collect1 = new ArrayList<>();
        SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        //今日新增陪护
        if (collect.size() > 0) {
            collect1 = collect.stream()
                    .filter(f -> formatter.format(f.getStartTime()).startsWith(today))
                    .collect(Collectors.toList());
        }
        //昨日新增陪护
        List<EscortAssociated> collect2 = collect.stream()
                .filter(f -> formatter.format(f.getStartTime()).startsWith(yesterday))
                .collect(Collectors.toList());

        //今日探视总数
        Integer count1 = visitAppointmentService.lambdaQuery()
                .like(VisitAppointment::getVisitDate, today)
                .eq(VisitAppointment::getAppointmentState, 0)
                .count();
        //今日已探视
        Integer count2 = visitAppointmentService.lambdaQuery()
                .like(VisitAppointment::getVisitDate, today)
                .eq(VisitAppointment::getAppointmentState, 0)
                .eq(VisitAppointment::getVisitState, 2)
                .count();
        //昨日探视总数
        Integer count3 = visitAppointmentService.lambdaQuery()
                .like(VisitAppointment::getVisitDate, yesterday)
                .eq(VisitAppointment::getAppointmentState, 0)
                .count();
        return Response.success(new TodayHospitalVO(todayPatient,
                count, todayPatient - yesterdayPatient, collect1.size(), collect.size(),
                collect1.size() - collect2.size(), count1, count2, count1 - count3));
    }

    @GetMapping("/backlogVisitApply")
    @ApiOperation(value = "代办探视申请", response = BacklogVisitApplyDTO.class)
    public Response backlogVisitApply(HttpServletRequest request, Page page) throws BizException {
        Integer userId = getUserId(request);
        Assert.isNull(userId, "当前未登录!");
        Manager byId = managerService.getById(userId);
        Assert.isNull(byId, "此用户不存在!");
        Integer areaId = null;
        if (byId.getRoleId() == 3) {
            areaId = byId.getInpatientAreaId();
        }
        Page<BacklogVisitApplyDTO> backlogVisitApplyVOPage = noticeService.backlogVisitApply(page, areaId);
        List<BacklogVisitApplyDTO> records = backlogVisitApplyVOPage.getRecords();
        for (BacklogVisitApplyDTO vo : records) {
            vo.setContent(vo.getSponsorName() + "申请探视" + vo.getReceiverName() + ",探视时间" + vo.getVisitDate() + " "
                    + cutOutTime(vo.getVisitStartTime()) + "-" + cutOutTime(vo.getVisitEndTime()));
        }
        backlogVisitApplyVOPage.setRecords(records);
        return Response.success(backlogVisitApplyVOPage);
    }

    @GetMapping("/backlogVisitApplyPage")
    @ApiOperation(value = "代办探视申请Page", response = BacklogVisitApplyPageDTO.class)
    @ApiImplicitParams({
            @ApiImplicitParam(dataType = "String", name = "condition", value = "姓名/手机号/床位号"),
            @ApiImplicitParam(dataType = "Integer", name = "result", value = "0:待处理 1:已处理"),
    })
    public Response backlogVisitApplyPage(HttpServletRequest request, Page page, String condition, Integer result) throws UnsupportedEncodingException, BizException {
        if (null != condition) {
            condition = URLDecoder.decode(condition, StandardCharsets.UTF_8.name());
        }
        Integer userId = getUserId(request);
        Assert.isNull(userId, "当前未登录!");
        Manager byId = managerService.getById(userId);
        Assert.isNull(byId, "此用户不存在!");
        Integer areaId = null;
        if (byId.getRoleId() == 3) {
            areaId = byId.getInpatientAreaId();
        }
        Page<BacklogVisitApplyPageDTO> backlogVisitApplyVOPage = noticeService.backlogVisitApplyPage(page, condition, result, areaId);
        List<BacklogVisitApplyPageDTO> records = backlogVisitApplyVOPage.getRecords();
        for (BacklogVisitApplyPageDTO vo : records) {
            vo.setContent(vo.getVisitDate() + " "
                    + cutOutTime(vo.getVisitStartTime()) + "-" + cutOutTime(vo.getVisitEndTime()));
        }
        backlogVisitApplyVOPage.setRecords(records);
        return Response.success(backlogVisitApplyVOPage);
    }

    @GetMapping("/backlogVisitApplyExcel")
    @ApiOperation(value = "代办探视申请Excel导出", response = BacklogVisitApplyPageDTO.class)
    @ApiImplicitParams({
            @ApiImplicitParam(dataType = "String", name = "condition", value = "姓名/手机号/床位号"),
            @ApiImplicitParam(dataType = "Integer", name = "result", value = "0:待处理 1:已处理"),
    })
    public void backlogVisitApplyExcel(HttpServletRequest request, HttpServletResponse response, String condition, Integer result) throws IOException, BizException {
        if (null != condition) {
            condition = URLDecoder.decode(condition, StandardCharsets.UTF_8.name());
        }
        Integer userId = getUserId(request);
        Assert.isNull(userId, "当前未登录!");
        Manager byId = managerService.getById(userId);
        Assert.isNull(byId, "此用户不存在!");
        Integer areaId = null;
        if (byId.getRoleId() == 3) {
            areaId = byId.getInpatientAreaId();
        }
        List<BacklogVisitApplyPageDTO> backlogVisitApplyPageDTOS = noticeService.backlogVisitApplyExcel(condition, result, areaId);
        List<BacklogVisitApplyPageDTO> records = backlogVisitApplyPageDTOS;
        for (BacklogVisitApplyPageDTO vo : records) {
            vo.setContent(vo.getVisitDate() + " "
                    + cutOutTime(vo.getVisitStartTime()) + "-" + cutOutTime(vo.getVisitEndTime()));
        }
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm");
        String date = sdf.format(new Date());
        String fileName = date + "探视申请记录.xlsx";
        response.setHeader("Content-Disposition", "attachment;filename=" + new String(fileName.getBytes("UTF-8"), "ISO-8859-1"));
        EasyExcel.write(response.getOutputStream(), BacklogVisitApplyPageDTO.class).sheet("探视申请记录").doWrite(backlogVisitApplyPageDTOS);
    }


    @GetMapping("/backlogEscortApply")
    @ApiOperation(value = "代办陪护申请", response = BacklogEscorApplyDTO.class)
    public Response backlogEscortApply(HttpServletRequest request, Page page) throws BizException {
        Integer userId = getUserId(request);
        Assert.isNull(userId, "当前未登录!");
        Manager byId = managerService.getById(userId);
        Assert.isNull(byId, "此用户不存在!");
        Integer areaId = null;
        if (byId.getRoleId() == 3) {
            areaId = byId.getInpatientAreaId();
        }
        Page<BacklogEscorApplyDTO> backlogEscorApplyDTOPage = noticeService.backlogEscortApply(page, areaId);
        List<BacklogEscorApplyDTO> records = backlogEscorApplyDTOPage.getRecords();
        for (BacklogEscorApplyDTO dto : records) {
            dto.setContent(dto.getPatientName() + "向" + dto.getEscortName() + "发起陪护关联");
        }
        backlogEscorApplyDTOPage.setRecords(records);
        return Response.success(backlogEscorApplyDTOPage);
    }

    @GetMapping("/backlogEscortApplyPage")
    @ApiOperation(value = "代办陪护申请Page", response = BacklogEscorApplyPageDTO.class)
    @ApiImplicitParams({
            @ApiImplicitParam(dataType = "String", name = "condition", value = "姓名/手机号/床位号"),
            @ApiImplicitParam(dataType = "Integer", name = "result", value = "0:待处理 1:已处理"),
    })
    public Response backlogEscortApplyPage(HttpServletRequest request, Page page, String condition, Integer result) throws BizException, UnsupportedEncodingException {
        if (null != condition) {
            condition = URLDecoder.decode(condition, StandardCharsets.UTF_8.name());
        }
        Integer userId = getUserId(request);
        Assert.isNull(userId, "当前未登录!");
        Manager byId = managerService.getById(userId);
        Assert.isNull(byId, "此用户不存在!");
        Integer areaId = null;
        if (byId.getRoleId() == 3) {
            areaId = byId.getInpatientAreaId();
        }
        Page<BacklogEscorApplyPageDTO> backlogEscorApplyPageDTOPage = noticeService.backlogEscortApplyPage(page, condition, result, areaId);
        return Response.success(backlogEscorApplyPageDTOPage);
    }


    @GetMapping("/backlogEscortApplyExcel")
    @ApiOperation(value = "代办陪护申请Excel导出", response = BacklogEscorApplyPageDTO.class)
    @ApiImplicitParams({
            @ApiImplicitParam(dataType = "String", name = "condition", value = "姓名/手机号/床位号"),
            @ApiImplicitParam(dataType = "Integer", name = "result", value = "0:待处理 1:已处理"),
    })
    public void backlogEscortApplyExcel(HttpServletRequest request, HttpServletResponse response, String condition, Integer result) throws IOException, BizException {
        if (null != condition) {
            condition = URLDecoder.decode(condition, StandardCharsets.UTF_8.name());
        }
        Integer userId = getUserId(request);
        Assert.isNull(userId, "当前未登录!");
        Manager byId = managerService.getById(userId);
        Assert.isNull(byId, "此用户不存在!");
        Integer areaId = null;
        if (byId.getRoleId() == 3) {
            areaId = byId.getInpatientAreaId();
        }
        List<BacklogEscorApplyPageDTO> backlogEscorApplyPageDTOS = noticeService.backlogEscortApplyExcel(condition, result, areaId);
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm");
        String date = sdf.format(new Date());
        String fileName = date + "陪护申请记录.xlsx";
        response.setHeader("Content-Disposition", "attachment;filename=" + new String(fileName.getBytes("UTF-8"), "ISO-8859-1"));
        EasyExcel.write(response.getOutputStream(), BacklogEscorApplyPageDTO.class).sheet("陪护申请记录").doWrite(backlogEscorApplyPageDTOS);
    }

    @GetMapping("/wardTodayVisit")
    @ApiOperation(value = "病区今日探视", response = WardTodayVisitDTO.class)
    public Response wardTodayVisit(Page page) {
        Page<WardTodayVisitDTO> wardTodayVisitDTOPage = noticeService.wardTodayVisit(page);
        return Response.success(wardTodayVisitDTOPage);
    }

    @PostMapping("/backlogDispose")
    @ApiOperation(value = "护士站消息处理")
    public Response backlogDispose(@RequestBody @ApiParam(value = "updateNoticeDataDTO", name = "UpdateNoticeDataDTO")
                                           UpdateNoticeDataDTO updateNoticeDataDTO) throws BizException, InterruptedException, URISyntaxException {
        Assert.isNull(updateNoticeDataDTO.getId(), "传入id为空！");
        Assert.isNull(updateNoticeDataDTO.getResult(), "尚未告诉我您是否同意！");
        Boolean aBoolean = false;
        // 防止不同患者同时同意成为正在陪护
        Integer id = updateNoticeDataDTO.getId();
        // 个人处理消息
        updateNoticeDataDTO.setDisposeType(1);
        Notice notice = noticeService.getById(id);
        Assert.isNull(notice, "系统正在开小差!");
        // 如果是设置用户成为陪护，则加锁避免超出规则
        if (notice.getType() == 1 && updateNoticeDataDTO.getResult() == 2) {
            Lock lockPatientId = redisLockRegistry.obtain(RedisConstants.LOCK_APPLY_ADDPATIENT_ESCORT +
                    escortAssociatedService.getById(notice.getAssociationId()).getUserId());
            if (!lockPatientId.tryLock(10, TimeUnit.SECONDS)) {
                throw new BizException("该用户被关联次数过于频繁!");
            }
            try {
                aBoolean = noticeService.updateNoticeData(updateNoticeDataDTO.setNotice(notice));
            } finally {
                lockPatientId.unlock();
            }
        } else {
            aBoolean = noticeService.updateNoticeData(updateNoticeDataDTO.setNotice(notice));
        }
        return Response.success(aBoolean);
    }


    private String cutOutTime(String time) {
        String substring = "";
        if (time != null) {
            substring = time.substring(11, 16);
        } else {
            log.error("时间格式错误!");
        }
        return substring;
    }
}
